#include "glwidget.h"
#include <QtOpenGL/QOpenGLFunctions_3_3_Compatibility>

static QString vertexSource = R"__(

	in vec4 vertex;
	uniform mat4	 matrix;
	void main(void)
	{
		gl_Position =  matrix* vertex;
	}

)__";

static QString fragmentUniformsSource = R"__(

	uniform vec3    iResolution;           // viewport resolution (in pixels)
	uniform float   iTime;           // shader playback time (in seconds)
	uniform float   iTimeDelta;           // shader playback time (in seconds)
	uniform vec4    iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
	uniform vec4    iDate;                 // (year, month, day, time in seconds)

	uniform int		iFrame;
	uniform float	iFrameRate;

	uniform float     iChannelTime[4];       // channel playback time (in seconds)
 	uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
 	
 	uniform sampler2D iChannel0;			// input channel. XX = 2D/Cube
 	uniform sampler2D iChannel1;
 	uniform sampler2D iChannel2;
 	uniform sampler2D iChannel3;
 	uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

)__";

static QString fragmentSource = R"__(

void main(void)
{
	vec4 fragColor=vec4(1.0,1.0,1.0,1.0);
	vec2 fragCoord=gl_FragCoord.xy;

	mainImage(fragColor,fragCoord);

	gl_FragColor = vec4( fragColor.xyz, fragColor.w );
}

)__";


static auto defaultSource = R"__(
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 p = (2.0*fragCoord-iResolution.xy)/min(iResolution.y,iResolution.x);
	
	p.y -= 0.25;

    // background color
    vec3 bcol = vec3(1.0,0.8,0.7-0.07*p.y)*(1.0-0.25*length(p));

    // animate
    float tt = mod(iTime,1.5)/1.5;
    float ss = pow(tt,.2)*0.5 + 0.5;
    ss = 1.0 + ss*0.5*sin(tt*6.2831*3.0 + p.y*0.5)*exp(-tt*4.0);
    p *= vec2(0.5,1.5) + ss*vec2(0.5,-0.5);
   

    // shape
    float a = atan(p.x,p.y)/3.141593;
    float r = length(p);
    float h = abs(a);
    float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h);

	// color
	float s = 1.0-0.5*clamp(r/d,0.0,1.0);
	s = 0.75 + 0.75*p.x;
	s *= 1.0-0.25*r;
	s = 0.5 + 0.6*s;
	s *= 0.5+0.5*pow( 1.0-clamp(r/d, 0.0, 1.0 ), 0.1 );
	vec3 hcol = vec3(1.0,0.5*r,0.3)*s;
	
    vec3 col = mix( bcol, hcol, smoothstep( -0.01, 0.01, d-r) );

    fragColor = vec4(col,1.0);
}


)__";

extern QString ChristmasTree;

glWidget::glWidget(QWidget* parent)
	: QOpenGLWidget(parent)
{
	ui.setupUi(this);

	this->setWindowTitle("merry christmas!!!");

	this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowTransparentForInput);
	this->setAttribute(Qt::WA_TranslucentBackground);
	//this->setAttribute(Qt::WA_AlwaysStackOnTop);
	//this->setStyleSheet("border:0px;\n"  "background-color:transparent;");

	QSurfaceFormat ft = QSurfaceFormat::defaultFormat();
	ft.setVersion(3, 3);
	ft.setAlphaBufferSize(8);
	ft.setSamples(8);
	ft.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
	setFormat(ft);


	QTimer* timer = new QTimer(this);
	connect(timer, &QTimer::timeout, [=]
	{
		this->update();
	});
	timer->start(20);
}

glWidget::~glWidget()
{

}

void glWidget::initializeGL()
{
	auto _gl = context()->functions();

	_gl->glEnable(GL_DEPTH_TEST);
	_gl->glEnable(GL_CULL_FACE);

	_gl->glClearColor(1, 0, 0, 1);

	_vertex = new QOpenGLShader(QOpenGLShader::Vertex, this);

	_fragment = new QOpenGLShader(QOpenGLShader::Fragment, this);

	_program = new QOpenGLShaderProgram(this);


	_vertex->compileSourceCode(vertexSource);

	_fragment->compileSourceCode(fragmentUniformsSource + ChristmasTree + fragmentSource);


	_program->addShader(_vertex);
	_program->addShader(_fragment);


	_program->link();



	_start = std::chrono::high_resolution_clock::now();


}

void glWidget::setFragmentSource(QString const& code)
{
	_fragment->compileSourceCode(fragmentUniformsSource + code + fragmentSource);
	_program->link();

	qDebug() << _program->log();

	if(!_program->isLinked())
	{
		_fragment->compileSourceCode(fragmentUniformsSource + defaultSource + fragmentSource);
		_program->link();
	}
	_start = std::chrono::high_resolution_clock::now();

}

void glWidget::resizeGL(int w, int h)
{
	auto _gl = context()->functions();

	_gl->glViewport(0, 0, w, h);

	_program->bind();

	_program->release();

}


void glWidget::paintGL()
{
	auto now = std::chrono::high_resolution_clock::now();
	std::chrono::duration<float> second = (now - _start);

	float width = this->width(), height = this->height();

	auto _gl = context()->functions();

	_gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	_program->bind();


	_program->setUniformValue("iTime", second.count());

	QMatrix4x4 mt;
	mt.ortho(0, width, 0, height, -1, 1);
	_program->setUniformValue("matrix", mt);


	QVector3D resolution;
	resolution = { width, height, 1 };
	_program->setUniformValue("iResolution", resolution);

	{
		auto date = QDate::currentDate();
		_program->setUniformValue("iDate", QVector4D(date.year(), date.month(), date.day(), QTime::currentTime().msecsSinceStartOfDay() / 1000.));
	}

	_program->enableAttributeArray("vertex");
	QVector3D vertex[4];
	vertex[0] = { 0, 0, 0, };
	vertex[1] = { width, 0, 0 };
	vertex[2] = { width, height, 0 };
	vertex[3] = { 0, height, 0 };
	_program->setAttributeArray("vertex", vertex);

	_gl->glDrawArrays(GL_QUADS, 0, 4);
	_program->disableAttributeArray("vertex");

	_program->release();


}

void glWidget::mouseMoveEvent(QMouseEvent* e)
{
	if(e->buttons() & Qt::LeftButton)
	{
		float x = e->localPos().x();
		float y = e->localPos().y();
		_mouse.setX(x);
		_mouse.setY(y);
		_program->bind();
		_program->setUniformValue("iMouse", _mouse);
	}
}

void glWidget::mousePressEvent(QMouseEvent* e)
{
	if(e->buttons() & Qt::LeftButton)
	{
		float x = e->localPos().x();
		float y = e->localPos().y();
		_mouse = QVector4D{ x,y,x,y };
	}
}

